<script lang="ts" setup name="InputNumberFloat">
interface Emits {
  (e: 'update:modelValue', value: number): void
}

const props = defineProps({
  modelValue: {
    type: Number,
    default: 0,
  },
  min: {
    type: Number,
    default: null,
  },
  max: {
    type: Number,
    default: null,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  w: {
    type: [Number, String],
    default: 100,
  },
})

const emit = defineEmits<Emits>()

// 内部用字符串保存展示值（这样才能控制 0）
const displayValue = ref('')

watch(
  () => props.modelValue,
  (val) => {
    // 保证外部传入时显示正确（blur 后格式）
    displayValue.value = formatBlur(val)
  },
  { immediate: true }
)
// focus 时处理
const handleFocus = () => {
  displayValue.value = formatFocus(displayValue.value)
}

// blur 时处理并更新 modelValue
const handleBlur = () => {
  const val = formatBlur(displayValue.value)
  displayValue.value = val
  if (props.min || props.max) {
    if (Number(val) > props.max || Number(val) < props.min) {
      displayValue.value = '0.00'
      emit('update:modelValue', Number(Number('0.00').toFixed(2)))
    } else {
      emit('update:modelValue', Number(Number(val).toFixed(2)))
    }
  } else {
    emit('update:modelValue', Number(Number(val).toFixed(2)))
  }
}

// 输入时只允许数字和小数点
const handleInput = (val: string) => {
  val = val.replace(/[^\d.]/g, '')
  displayValue.value = val
}

// 🔹 focus 格式：去掉多余 0
function formatFocus(val: string | number): string {
  if (val === '' || val === null) return ''
  let str = String(val)
  if (str.includes('.')) {
    // 去掉末尾 0
    str = str.replace(/\.?0+$/, '')
  }
  return str
}

// 🔹 blur 格式：小数点规则
function formatBlur(val: string | number): string {
  if (val === '' || val === null) return '0.00'
  let num = Number(val)
  if (isNaN(num)) return '0.00'
  let str = String(val)

  if (!str.includes('.')) {
    return num.toFixed(2) // 补 .00
  }

  const decimal = str.split('.')[1] || ''
  if (decimal.length === 0) {
    return num.toFixed(2)
  } else if (decimal.length === 1) {
    return num.toFixed(2) // 补 1 个 0
  } else {
    return str // 保留原样
  }
}
const innerRef = ref()

// computed style，带 !important
const inputStyle = computed(() => `width: ${props.w}% !important`)
// 阻止顶层div吃掉属性
defineOptions({
  inheritAttrs: false,
})
// ✅ 暴露 focus / select / blur 等方法给父组件用
defineExpose({
  focus: () => innerRef.value?.focus?.(),
  blur: () => innerRef.value?.blur?.(),
  select: () => innerRef.value?.select?.(),
  getRef: () => innerRef.value,
})
</script>

<template>
  <!-- <div> -->
  <!-- 输入框 -->
  <el-input
    ref="innerRef"
    v-bind="$attrs"
    v-model="displayValue"
    class="w100"
    :disabled="props.disabled"
    :style="inputStyle"
    @blur="handleBlur"
    @focus="handleFocus"
    @input="handleInput"
  >
    <template #prefix>
      <slot name="prefix"></slot>
    </template>
    <template #suffix>
      <slot name="suffix"></slot>
    </template>
  </el-input>
  <!-- </div> -->
</template>

<style lang="scss" scoped></style>
